﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;

namespace Faz.SideWinderSC.Client
{
    /// <summary>
    /// Provides conversion of <see cref="ConsoleKey"/> values from and to <see cref="Key"/> values.
    /// </summary>
    public class ConsoleKeyToKeyConverter : IValueConverter
    {
        private static readonly IDictionary<ConsoleKey, Key> convertNames;

        static ConsoleKeyToKeyConverter()
        {
            convertNames = new Dictionary<ConsoleKey, Key>();
            convertNames.Add(ConsoleKey.Backspace, Key.Back);
            convertNames.Add(ConsoleKey.Spacebar, Key.Space);
            convertNames.Add(ConsoleKey.LeftArrow, Key.Left);
            convertNames.Add(ConsoleKey.RightArrow, Key.Right);
            convertNames.Add(ConsoleKey.UpArrow, Key.Up);
            convertNames.Add(ConsoleKey.DownArrow, Key.Down);
            convertNames.Add(ConsoleKey.LeftWindows, Key.LWin);
            convertNames.Add(ConsoleKey.RightWindows, Key.RWin);
            convertNames.Add(ConsoleKey.Applications, Key.Apps);
            convertNames.Add(ConsoleKey.MediaNext, Key.MediaNextTrack);
            convertNames.Add(ConsoleKey.MediaPrevious, Key.MediaPreviousTrack);
            convertNames.Add(ConsoleKey.MediaPlay, Key.MediaPlayPause);
            convertNames.Add(ConsoleKey.LaunchMediaSelect, Key.SelectMedia);
            convertNames.Add(ConsoleKey.LaunchApp1, Key.LaunchApplication1);
            convertNames.Add(ConsoleKey.LaunchApp2, Key.LaunchApplication2);
            convertNames.Add(ConsoleKey.Process, Key.ImeProcessed);
            convertNames.Add(ConsoleKey.Packet, Key.System);
            convertNames.Add(ConsoleKey.Attention, Key.Attn);
            convertNames.Add(ConsoleKey.EraseEndOfFile, Key.EraseEof);
        }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is ConsoleKey && targetType == typeof(Key))
            {
                ConsoleKey console = (ConsoleKey)value;
                if (convertNames.ContainsKey(console))
                {
                    return convertNames[console];
                }

                Key result;
                if (Enum.TryParse<Key>(console.ToString(), out result))
                {
                    return result;
                }
            }
            else if (value is ICollection<ConsoleKey>)
            {
                ICollection<ConsoleKey> source = (ICollection<ConsoleKey>)value;
                return source.Select(k => this.Convert(k, typeof(Key), null, culture)).ToList();
            }

            return DependencyProperty.UnsetValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is Key && targetType == typeof(ConsoleKey))
            {
                Key key = (Key)value;
                if (convertNames.Values.Contains(key))
                {
                    return convertNames.First(p => p.Value == key).Key;
                }

                ConsoleKey result;
                if (Enum.TryParse<ConsoleKey>(key.ToString(), out result))
                {
                    return result;
                }
            }
            else if (value is ICollection<Key>)
            {
                ICollection<Key> source = (ICollection<Key>)value;
                return source.Select(k => this.ConvertBack(k, typeof(ConsoleKey), null, culture)).ToList();
            }

            return DependencyProperty.UnsetValue;
        }
    }
}
